﻿Ext.data.Reader = Ext.extend(Object, {

    idProperty: 'id',

    //检索dataset中的总记录数的属性的名称
    //如果不是一下子获取数据集的全部数据，并且又在远程服务器上分页，这个属性才有需要用到。默认为'total'。
    totalProperty: 'total',

    //检索的成功属性的属性的名称。默认success
    successProperty: 'success',


    root: '',


    implicitIncludes: true,

    // 读取不到数据时返回的数据集
    nullResultSet: new Ext.data.ResultSet({
        total: 0,
        count: 0,
        records: [],
        success: true
    }),

    constructor: function (config) {
        Ext.apply(this, config || {});

        // 获取模型
        this.model = Ext.ModelMgr.getModel(config.model);


        if (this.model) {
            this.buildExtractors();// 创建各种性质的属性存取器
        }
    },

    // 设置新模型
    setModel: function (model, setOnProxy) {
        this.model = Ext.ModelMgr.getModel(model);
        this.buildExtractors(true);// 创建各种性质的属性存取器（将原有的清空）

        // 代理跟这更新模型
        if (setOnProxy && this.proxy) {
            this.proxy.setModel(this.model, true);
        }
    },

    //读取给定的response对象，并且在将记录传递给readRecords方法之前将不同类型的response对象标准化
    read: function (response) {
        var data = response;

        if (response && response.responseText) {
            data = this.getResponseData(response); //将response里面的记录转换成特定形式（json或xml）的记录
        }

        if (data) {
            return this.readRecords(data); //返回Ext.data.ResultSet对象
        } else {
            return this.nullResultSet; // 没有数据时的Ext.data.ResultSet对象
        }
    },

    //所有Reader的子类的通用抽象接口。返回Ext.data.ResultSet对象
    //每个子类都在运行自身的逻辑并返回Ext.data.ResultSet实例之前调用此方法。对于大多数读者并不需要额外的处理应。
    readRecords: function (data) {

        this.rawData = data;

        data = this.getData(data);//统一格式。如果是xml形式，还有有一定的转换

        var root = this.getRoot(data), //获取this.root为根的数据
            total = root.length,
            success = true,
            value, records, recordCount;

        if (this.totalProperty) {
            value = parseInt(this.getTotal(data), 10);//把字符串转换为整数，以10进制来解析
            if (!isNaN(value)) {
                total = value;
            }
        }

        if (this.successProperty) {
            value = this.getSuccess(data);
            if (value === false || value === 'false') {
                success = false;
            }
        }

        records = this.extractData(root, true);// 萃取模型数据集合root的数据
        recordCount = records.length;

        return new Ext.data.ResultSet({//返回Ext.data.ResultSet对象
            total: total || recordCount,
            count: recordCount,
            records: records,
            success: success
        });
    },

    // 萃取模型数据集合root的数据
    extractData: function (root, returnRecords) {
        var values = [],
            records = [],
            Model = this.model,
            length = root.length,
            idProp = this.idProperty,
            node, id, record, i;

        // 遍历根数据root
        for (i = 0; i < length; i++) {
            node = root[i]; // 根数据的子元素
            values = this.extractValues(node); // 获取node经过萃取后的值
            id = this.getId(node);

            // 如果返回的是记录
            if (returnRecords === true) {
                record = new Model(values, id);
                record.raw = node;
                records.push(record);

                if (this.implicitIncludes) {
                    this.readAssociated(record, node);// 与关联模型的数据相互关联（单向和双向）
                }
            } else { // 返回数组
                values[idProp] = id;
                records.push(values);
            }
        }

        return records;
    },

    // 与关联模型的数据相互关联（单向和双向）
    readAssociated: function (record, data) {
        var associations = record.associations.items, // 各关联模型数据
            length = associations.length,
            association, associationName, associatedModel, associationData, inverseAssociation, proxy, reader, store, i;

        // 遍历关联记录
        for (i = 0; i < length; i++) {
            association = associations[i]; // 当前关联记录
            associationName = association.name; // 当前关联记录模型名
            associationData = this.getAssociatedDataRoot(data, association.associationKey || associationName); // 当前关联记录的原数据
            associatedModel = association.associatedModel; // 当前关联记录的关联模型

            // 如果关联模型有数据
            if (associationData) {
                proxy = associatedModel.proxy;

                // 如果关联记录制定了代理
                if (proxy) {
                    reader = proxy.getReader();
                } else {
                    reader = new this.constructor({
                        model: association.associatedName
                    });
                }

                // 如果说hasMany关联
                if (association.type == 'hasMany') {

                    store = record[associationName](); // 当前记录下对应关联模型的子存储（这是在从模型对象初始化时注册到主模型对象中的）

                    store.add.apply(store, reader.read(associationData).records); // 当前记录下对应关联模型的子存储增加关联数据


                    // 查询关联模型中的关联模型，后者满足type为'belongsTo'且associatedName正好也是本模型的模型名
                    inverseAssociation = associatedModel.prototype.associations.findBy(function (assoc) {
                        return assoc.type == 'belongsTo' && assoc.associatedName == record.constructor.modelName;
                    });

                    // 如果存在双向关联的模型，则关联模型中的对应数据也指向本数据
                    if (inverseAssociation) {
                        store.data.each(function (associatedRecord) {
                            associatedRecord[inverseAssociation.instanceName] = record;
                        });
                    }

                } else if (association.type == 'belongsTo') { // 如果是 'belongsTo' ，则对应属性指向上级存储
                    record[association.instanceName] = reader.read([associationData]).records[0];
                }
            }
        }
    },


    getAssociatedDataRoot: function (data, associationName) {
        return data[associationName];
    },

    // 获取data经过萃取后的值
    extractValues: function (data) {
        var fields = this.model.prototype.fields.items, // 模块中的属性
            length = fields.length,
            output = {},
            field, value, i;

        // 遍历模块中的属性（属性索引与萃取方法索引一致，所以能找到对应的萃取方法）
        for (i = 0; i < length; i++) {
            field = fields[i]; // 当前属性
            value = this.extractorFunctions[i](data) || field.defaultValue; // 当前属性萃取值

            output[field.name] = value;
        }

        return output; // 返回data经过萃取后的数据
    },

    //具体方法在子类实现，起到统一数据格式的作用
    getData: function (data) {
        return data;
    },

    //返回this.root指定为根的数据
    getRoot: function (data) {
        return data;
    },


    getResponseData: function (response) {
        throw new Error("getResponseData must be implemented in the Ext.data.Reader subclass");
    },


    onMetaChange: function (meta) {
        var fields = meta.fields,
            newModel;

        Ext.apply(this, meta);

        if (fields) {
            newModel = Ext.regModel("JsonReader-Model" + Ext.id(), { fields: fields });
            this.setModel(newModel, true);
        } else {
            this.buildExtractors(true);
        }
    },

    // 创建各种性质的属性存取器
    buildExtractors: function (force) {
        if (force === true) {
            delete this.extractorFunctions;
        }

        if (this.extractorFunctions) {
            return;
        }

        var idProp = this.id || this.idProperty,
            totalProp = this.totalProperty,
            successProp = this.successProperty,
            messageProp = this.messageProperty;

        // 如果定义了totalProperty字段
        if (totalProp) {
            this.getTotal = this.createAccessor(totalProp); // 创建totalProperty字段的存取器
        }

        // 如果定义了successProperty字段
        if (successProp) {
            this.getSuccess = this.createAccessor(successProp);// 创建successProperty字段的存取器
        }

        // 如果定义了messageProperty字段
        if (messageProp) {
            this.getMessage = this.createAccessor(messageProp);// 创建messageProperty字段的存取器
        }

        // 如果定义了id或idProperty字段
        if (idProp) {
            var accessor = this.createAccessor(idProp);// 创建idProperty字段的存取器

            this.getId = function (record) {
                var id = accessor(record);

                return (id == undefined || id == '') ? null : id; // 在获取id后，将未定义或者空字符串的状态统一为null
            };
        } else {
            this.getId = function () { // 如果未定义则同意返回null
                return null;
            };
        }
        this.buildFieldExtractors();// 创建一般属性存取器
    },

    // 创建一般属性存取器
    buildFieldExtractors: function () {

        var fields = this.model.prototype.fields.items, // 模型中的属性数组
            ln = fields.length,
            i = 0,
            extractorFunctions = [],
            field, map;

        // 遍历每个模型的属性
        for (; i < ln; i++) {
            field = fields[i];
            map = (field.mapping !== undefined && field.mapping !== null) ? field.mapping : field.name; 

            extractorFunctions.push(this.createAccessor(map)); // 属性的存取器
        }

        this.extractorFunctions = extractorFunctions;
    }
});